﻿using System;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using JY.Wpf.Controls.ControlHelpers;
using JY.Wpf.Core.Tools;

namespace JY.Wpf.Controls.Controls
{
    /// <summary>
    /// 步骤条
    /// </summary>
    public class StepBar : ItemsControl
    {
        #region Private属性

        private ScrollViewer mScrollViewer;
        #endregion
        
        #region 依赖属性定义

        #region Progress

        public int Progress
        {
            get { return (int)this.GetValue(StepBar.ProgressProperty); }
            set { this.SetValue(StepBar.ProgressProperty, value); }
        }

        public static readonly DependencyProperty ProgressProperty =
            DependencyProperty.Register("Progress", typeof(int), typeof(StepBar), new PropertyMetadata(0, StepBar.OnProgressChangedCallback, StepBar.OnProgressCoerceValueCallback));

        private static object OnProgressCoerceValueCallback(DependencyObject d, object baseValue)
        {
            //不让Progress超出边界
            StepBar stepBar = d as StepBar;
            int newValue = Convert.ToInt32(baseValue);
            if (newValue < 0)
            {
                return 0;
            }
            else if (newValue >= stepBar.Items.Count)
            {
                return stepBar.Items.Count - 1;
            }
            object item = stepBar.Items[newValue];
            stepBar.ScrollToSelection(item);
            return newValue;
        }

        private static void OnProgressChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }

        #endregion

        #region ItemWidth

        public double ItemWidth
        {
            get { return (double)this.GetValue(StepBar.ItemWidthProperty); }
            set { this.SetValue(StepBar.ItemWidthProperty, value); }
        }
        
        public static readonly DependencyProperty ItemWidthProperty =
            DependencyProperty.Register("ItemWidth", typeof(double), typeof(StepBar), new PropertyMetadata(50d));

        #endregion

        #endregion

        #region 依赖属性set get

        #endregion

        #region Constructors
        static StepBar()
        {
            FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(StepBar), new FrameworkPropertyMetadata(typeof(StepBar)));
        }
        #endregion

        #region Override方法

        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);
            this.mScrollViewer = VisualHelper.FindVisualChild<ScrollViewer>(this);
            if (this.mScrollViewer != null)
            {
                this.mScrollViewer.ScrollChanged += this.MScrollViewer_ScrollChanged;
            }
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new StepBarItem();
        }

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            //设置Item的显示数字
            StepBarItem stepBarItem = element as StepBarItem;
            ItemsControl itemsControl = ItemsControl.ItemsControlFromItemContainer(stepBarItem);
            int index = itemsControl.ItemContainerGenerator.IndexFromContainer(stepBarItem);
            stepBarItem.Number = Convert.ToString(++index);
            base.PrepareContainerForItemOverride(element, item);
        }

        protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
        {
            base.OnItemsChanged(e);

            //ItemsControl数量变化时，重新设置各个Item的显示的数字
            for (int i = 0; i < this.Items.Count; i++)
            {
                StepBarItem stepBarItem = this.ItemContainerGenerator.ContainerFromIndex(i) as StepBarItem;
                if(stepBarItem != null)
                {
                    int temp = i;
                    stepBarItem.Number = Convert.ToString(++temp);
                }
            }
        }
        #endregion

        #region Private方法

        /// <summary>
        /// 滚动至指定Item
        /// </summary>
        /// <param name="selection"></param>
        private void ScrollToSelection(object selection)
        {
            if (this.mScrollViewer == null)
            {
                return;
            }

            for (int i = 0; i < this.Items.Count; i++)
            {
                if (this.Items[i] == selection)
                {

                    //获取子项相对于控件的位置
                    var selectionItem = this.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;

                    GeneralTransform generalTransform1 = selectionItem.TransformToAncestor(this);
                    Point currentPoint = generalTransform1.Transform(new Point(0, 0));

                    double offsetX = this.mScrollViewer.VerticalOffset + currentPoint.X;

                    this.mScrollViewer.ScrollToHorizontalOffset(offsetX);

                    //DoubleAnimation doubleAnimation = new DoubleAnimation(this.oldOffsetY, offsetY, new Duration(TimeSpan.FromMilliseconds(500)));
                    //this.mScrollViewer.BeginAnimation(ZScrollViewer.VerticalOffsetExProperty, doubleAnimation);

                    //this.oldOffsetY = offsetY;
                    //this.IndicatorSelectedIndex = i;
                    break;
                }
            }
        }

        /// <summary>
        /// 当滚动条位置发生改变时，选中指示器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            var verticalOffset = this.mScrollViewer.VerticalOffset;
            if (verticalOffset > 0)
            {
                double scrollOffset = 0.0;
                for (int i = 0; i < this.Items.Count; i++)
                {
                    var child = this.Items[i];
                    if (child is FrameworkElement)
                    {
                        FrameworkElement element = child as FrameworkElement;
                        if (element == null) return;

                        scrollOffset += element.ActualHeight;

                        if (scrollOffset > verticalOffset && i < this.Items.Count)
                        {
                            //this.IndicatorSelectedIndex = i;
                            this.Progress = i;
                            break;
                        }
                    }
                }
            }
        }
        #endregion
    }
}
